
package org.apache.solr.search;

import java.net.URL;
import java.util.Map;
import org.apache.solr.core.SolrCore;
import org.apache.solr.core.SolrInfoMBean.Category;
import org.apache.solr.search.SolrCache.State;

/**
 * Common base class of reusable functionality for SolrCaches
 */
public abstract class SolrCacheBase {

    protected CacheRegenerator regenerator;
    private State state;
    private String name;
    protected AutoWarmCountRef autowarm;

    /**
     * Decides how many things to autowarm based on the size of another cache
     */
    public static class AutoWarmCountRef {

        private final int autoWarmCount;
        private final int autoWarmPercentage;
        private final boolean autoWarmByPercentage;
        private final boolean doAutoWarming;
        private final String strVal;

        public AutoWarmCountRef(final String configValue) {
            try {
                String input = (null == configValue) ? "0" : configValue.trim();

                // odd undocumented legacy behavior, -1 meant "all" (now "100%")
                strVal = ("-1".equals(input)) ? "100%" : input;

                if (strVal.indexOf("%") == (strVal.length() - 1)) {
                    autoWarmCount = 0;
                    autoWarmPercentage = Integer.parseInt(strVal.substring(0, strVal.length() - 1));
                    autoWarmByPercentage = true;
                    doAutoWarming = (0 < autoWarmPercentage);
                }
                else {
                    autoWarmCount = Integer.parseInt(strVal);
                    autoWarmPercentage = 0;
                    autoWarmByPercentage = false;
                    doAutoWarming = (0 < autoWarmCount);
                }

            }
            catch (Exception e) {
                throw new RuntimeException("Can't parse autoWarm value: " + configValue, e);
            }
        }

        @Override
        public String toString() {
            return strVal;
        }

        public boolean isAutoWarmingOn() {
            return doAutoWarming;
        }

        public int getWarmCount(final int previousCacheSize) {
            return autoWarmByPercentage
                    ? (previousCacheSize * autoWarmPercentage) / 100
                    : Math.min(previousCacheSize, autoWarmCount);
        }
    }

    /**
     * Returns a "Hit Ratio" (ie: max of 1.00, not a percentage) suitable for
     * display purposes.
     */
    protected static String calcHitRatio(long lookups, long hits) {

        if (lookups == 0) {
            return "0.00";
        }
        if (lookups == hits) {
            return "1.00";
        }
        int hundredths = (int) (hits * 100 / lookups);   // rounded down
        if (hundredths < 10) {
            return "0.0" + hundredths;
        }
        return "0." + hundredths;

        /**
         * * code to produce a percent, if we want it... int ones =
         * (int)(hits*100 / lookups); int tenths = (int)(hits*1000 / lookups) -
         * ones*10; return Integer.toString(ones) + '.' + tenths;
         */
    }

    public String getVersion() {
        return SolrCore.version;
    }

    public Category getCategory() {
        return Category.CACHE;
    }

    public URL[] getDocs() {
        return null;
    }

    public void init(Map<String, String> args, CacheRegenerator regenerator) {

        this.regenerator = regenerator;
        state = State.CREATED;
        name = (String) args.get("name");
        autowarm = new AutoWarmCountRef((String) args.get("autowarmCount"));

    }

    protected String getAutowarmDescription() {
        return "autowarmCount=" + autowarm + ", regenerator=" + regenerator;
    }

    protected boolean isAutowarmingOn() {
        return autowarm.isAutoWarmingOn();
    }

    public void setState(State state) {
        this.state = state;
    }

    public State getState() {
        return state;
    }

    public String name() {
        return this.name;
    }
}
